﻿using FluentAssertions;
using Hopscotch.Presentation.Common.Collections;
using Hopscotch.Test.Presentation;
using Hopscotch.Test.Presentation.Threading;
using NUnit.Framework;


namespace Hopscotch.Presentation.Common.Test.Collections
{
    [TestFixture]
    public class DispatcherCollectionTest
    {
        private DeterministicDispatcher dispatcher;
        private DispatcherCollection<TestEntity, int> dispatcherCollection;

        [SetUp]
        public void SetUp()
        {
            dispatcher = new DeterministicDispatcher();
            dispatcherCollection = new DispatcherCollection<TestEntity, int>(dispatcher);
        }

        [Test]
        public void TestAddShouldRunOnDispatcher()
        {
            var entity = new TestEntity() { Id = 1 };

            dispatcherCollection.Add(entity);

            dispatcherCollection.Count.Should().Be(0);
            dispatcher.RunAllTasks();
            dispatcherCollection.Count.Should().Be(1);
        }

        [Test]
        public void TestMergeShouldQueueOnDispatcher()
        {
            var entity = new TestEntity() { Id = 1 };
            dispatcherCollection.Merge(entity);

            dispatcherCollection.Count.Should().Be(0);
            dispatcher.RunAllTasks();
            dispatcherCollection.Count.Should().Be(1);
        }

        [Test]
        public void TestRemoveShouldQueueOnDispatcher()
        {
            var entity = new TestEntity() { Id = 1 };
            dispatcherCollection.Add(entity);            
            dispatcherCollection.Remove(entity);
                        
            dispatcher.RunAllTasks();
            dispatcherCollection.Count.Should().Be(0);
        }

        [Test]
        public void TestCollectionShouldContainAddedItem()
        {
            var entity = new TestEntity() { Id = 1 };
            dispatcherCollection.Add(entity);

            dispatcher.RunAllTasks();
            dispatcherCollection.Should().Contain(entity);
        }

        [Test]
        public void TestCollectionAddRemoveShouldNotContainItem()
        {
            var entity = new TestEntity() { Id = 1 };
            dispatcherCollection.Add(entity);
            dispatcherCollection.Remove(entity);

            dispatcher.RunAllTasks();

            dispatcherCollection.Should().NotContain(entity);
        }

        [Test]
        public void TestCollectionMergeRemoveShouldNotContainItem()
        {
            var entity = new TestEntity() { Id = 1 };
            dispatcherCollection.Merge(entity);
            dispatcherCollection.Remove(entity);

            dispatcher.RunAllTasks();

            dispatcherCollection.Should().NotContain(entity);
            dispatcherCollection.Count.Should().Be(0);
        }

        [Test]
        public void TestCollectionMultipleMergeShouldSingleItem()
        {
            var entity = new TestEntity() { Id = 1 };
            dispatcherCollection.Merge(entity);
            dispatcherCollection.Merge(entity);
            dispatcherCollection.Merge(entity);

            dispatcher.RunAllTasks();

            dispatcherCollection.Count.Should().Be(1);
            dispatcherCollection.Should().Contain(entity);            
        }

        [Test]
        public void TestCollectionClearShouldBeEmpty()
        {
            dispatcherCollection.Merge(new TestEntity() { Id = 1 });
            dispatcherCollection.Merge(new TestEntity() { Id = 2 });
            
            dispatcher.RunAllTasks();
            dispatcherCollection.Count.Should().Be(2);

            dispatcherCollection.Clear();
            dispatcher.RunAllTasks();
            dispatcherCollection.Count.Should().Be(0);
        }
    }
}
